import { RouteObject } from "@/routers/interface";
import * as XLSX from "xlsx";
import { saveAs } from "file-saver";
import basicRoutes from "@/routers/basic";
import { cloneDeep } from "lodash-es";

/**
 * @description 获取localStorage
 * @param {string} key Storage名称
 * @return string
 */
export const localGet = (key: string) => {
	const value = window.localStorage.getItem(key);
	try {
		return JSON.parse(window.localStorage.getItem(key) as string);
	} catch (error) {
		return value;
	}
};

/**
 * @description 存储localStorage
 * @param {string} key Storage名称
 * @param {Any} value Storage值
 * @return void
 */
export const localSet = (key: string, value: any) => {
	window.localStorage.setItem(key, JSON.stringify(value));
};

/**
 * @description 清除localStorage
 * @param {string} key Storage名称
 * @return void
 */
export const localRemove = (key: string) => {
	window.localStorage.removeItem(key);
};

/**
 * @description 清除所有localStorage
 * @return void
 */
export const localClear = () => {
	window.localStorage.clear();
};

/**
 * @description 获取浏览器默认语言
 * @return string
 */
export const getBrowserLang = () => {
	let browserLang = navigator.language ? navigator.language : navigator.browserLanguage;
	let defaultBrowserLang = "";
	if (browserLang.toLowerCase() === "cn" || browserLang.toLowerCase() === "zh" || browserLang.toLowerCase() === "zh-cn") {
		defaultBrowserLang = "zh";
	} else if (browserLang.toLowerCase() === "vi") {
		defaultBrowserLang = "vi";
	} else {
		defaultBrowserLang = "en";
	}
	return defaultBrowserLang;
};

/**
 * @description 获取需要展开的 subMenu
 * @param {string} path 当前访问地址
 * @returns array
 */
export const getOpenKeys = (path: string) => {
	let newStr: string = "";
	let newArr: any[] = [];
	let arr = path.split("/").map(i => "/" + i);
	for (let i = 1; i < arr.length - 1; i++) {
		newStr += arr[i];
		newArr.push(newStr);
	}
	return newArr;
};

/**
 * @description 递归查询对应的路由
 * @param {string} path 当前访问地址
 * @param {Array} routes 路由列表
 * @returns object
 */
export const searchRoute = (path: string, routes: RouteObject[] = [], includeBasic: boolean = true): RouteObject => {
	let route = {};
	let baseRoutes = cloneDeep(basicRoutes);
	route = searchRouteByFull(path, [...(includeBasic ? baseRoutes : []), ...routes]);
	return route;
};

/**
 * @description 递归查询对应的路由
 * @param {string} path 当前访问地址
 * @param {Array} routes 路由列表
 * @returns object
 */
export const searchRouteByFull = (path: string, routes: RouteObject[] = []): RouteObject => {
	let result: RouteObject = {};
	for (let item of routes) {
		if (item.path === path) return item;
		if (item.children) {
			const res = searchRouteByFull(path, item.children);
			if (Object.keys(res).length) result = res;
		}
	}
	return result;
};

/**
 * @description 递归查询对应的路由
 * @param {string[]} paths 访问地址拆分数组
 * @param {Array} routes 路由列表
 * @returns object
 */
export const searchRouteByStructure = (paths: string[], routes: RouteObject[] = [], level: number = 0): RouteObject => {
	// if (isString(path)) {
	// 	paths = (path.startsWith("/") ? path.substring(1, path.length) : path).split("/") as string[];
	// 	paths[0] = "/" + paths[0];
	// }
	let result: RouteObject = {};
	for (let item of routes) {
		if (item.path === paths[level]) {
			if (paths.length - 1 === level) {
				console.log("匹配完成", item);
				return item;
			} else if (item.children) {
				++level;
				result = searchRouteByStructure(paths, item.children, level);
			}
			break;
		}
	}
	return result;
};

// 合并路由
export const mergeSamePathRoute = (base: RouteObject[], routes: RouteObject[]) => {
	let newRoutes = cloneDeep(routes);
	let newBaseRoutes = cloneDeep(base);
	newRoutes.forEach(route => {
		let index = base.findIndex(ele => ele.path === route.path);
		if (index !== -1) {
			route.children = [...(base[index]?.children ?? []), ...(route?.children ?? [])];
			newBaseRoutes.splice(index, 1);
		}
	});
	return [...newBaseRoutes, ...newRoutes];
};

/**
 * @description 递归当前路由的 所有 关联的路由，生成面包屑导航栏
 * @param {string} path 当前访问地址
 * @param {Array} menuList 菜单列表
 * @returns array
 */
export const getBreadcrumbList = (path: string, menuList: Menu.MenuOptions[]) => {
	let tempPath: any[] = [];
	try {
		const getNodePath = (node: Menu.MenuOptions) => {
			tempPath.push(node);
			// 找到符合条件的节点，通过throw终止掉递归
			if (node.path === path) {
				throw new Error("GOT IT!");
			}
			if (node.children && node.children.length > 0) {
				for (let i = 0; i < node.children.length; i++) {
					getNodePath(node.children[i]);
				}
				// 当前节点的子节点遍历完依旧没找到，则删除路径中的该节点
				tempPath.pop();
			} else {
				// 找到叶子节点时，删除路径当中的该叶子节点
				tempPath.pop();
			}
		};
		for (let i = 0; i < menuList.length; i++) {
			getNodePath(menuList[i]);
		}
	} catch (e) {
		return tempPath.map(item => item.name);
	}
};

/**
 * @description 双重递归 找出所有 面包屑 生成对象存到 redux 中，就不用每次都去递归查找了
 * @param {string} menuList 当前菜单列表
 * @returns object
 */
export const findAllBreadcrumb = (menuList: Menu.MenuOptions[]): { [key: string]: any } => {
	let handleBreadcrumbList: any = {};
	const loop = (menuItem: Menu.MenuOptions) => {
		// 下面判断代码解释 *** !item?.children?.length   ==>   (item.children && item.children.length > 0)
		if (menuItem?.children?.length) menuItem.children.forEach(item => loop(item));
		else handleBreadcrumbList[menuItem.path] = getBreadcrumbList(menuItem.path, menuList);
	};
	menuList.forEach(item => loop(item));
	return handleBreadcrumbList;
};

/**
 * @description 使用递归处理路由菜单，生成一维数组，做菜单权限判断
 * @param {Array} menuList 所有菜单列表
 * @param {Array} newArr 菜单的一维数组
 * @return array
 */
export function handleRouter(routerList: Menu.MenuOptions[], newArr: string[] = []) {
	routerList.forEach((item: Menu.MenuOptions) => {
		typeof item === "object" && item.path && newArr.push(item.path);
		item.children && item.children.length && handleRouter(item.children, newArr);
	});
	return newArr;
}

/**
 * @description 判断数据类型
 * @param {Any} val 需要判断类型的数据
 * @return string
 */
export const isType = (val: any) => {
	if (val === null) return "null";
	if (typeof val !== "object") return typeof val;
	else return Object.prototype.toString.call(val).slice(8, -1).toLocaleLowerCase();
};

/**
 * @description 对象数组深克隆
 * @param {Object} obj 源对象
 * @return object
 */
export const deepCopy = <T>(obj: any): T => {
	let newObj: any;
	try {
		newObj = obj.push ? [] : {};
	} catch (error) {
		newObj = {};
	}
	for (let attr in obj) {
		if (typeof obj[attr] === "object") {
			newObj[attr] = deepCopy(obj[attr]);
		} else {
			newObj[attr] = obj[attr];
		}
	}
	return newObj;
};

/**
 * @description 生成随机数
 * @param {Number} min 最小值
 * @param {Number} max 最大值
 * @return number
 */
export function randomNum(min: number, max: number): number {
	let num = Math.floor(Math.random() * (min - max) + max);
	return num;
}

//时间戳转换YYYY-MM-DD HH:MM:SS
export function TimeDate(time: number): string {
	let date = new Date(time);
	return `${date.getFullYear()}-${(date.getMonth() + 1).toString().padStart(2, "0")}-${date
		.getDate()
		.toString()
		.padStart(2, "0")} `;
	/* ${date.getHours().toString().padStart(2, "0")}:${date.getMinutes().toString().padStart(2, "0")}:${date
		.getSeconds()
		.toString()
		.padStart(2, "0")} */
}
//表格导出
export const exportToExcel = (dataSource: any, title: string) => {
	if (dataSource.length === 0) return;
	const worksheet = XLSX.utils.json_to_sheet(dataSource);
	const workbook = XLSX.utils.book_new();
	XLSX.utils.book_append_sheet(workbook, worksheet, "Sheet1");
	const excelBuffer = XLSX.write(workbook, { bookType: "xlsx", type: "array" });
	const blob = new Blob([excelBuffer], { type: "application/octet-stream" });
	saveAs(blob, title + ".xlsx");
};
export const mergeObjects = (obj1: any, obj2: any) => {
	let result = { ...obj1 };
	for (let key in obj2) {
		if (!Object.prototype.hasOwnProperty.call(result, key)) {
			result[key] = obj2[key];
		}
	}
	return result;
};
const hexList: string[] = [];
for (let i = 0; i <= 15; i++) hexList[i] = i.toString(16);

export const buildUUID = (): string => {
	let uuid = "";
	for (let i = 1; i <= 36; i++) {
		if (i === 9 || i === 14 || i === 19 || i === 24) uuid += "-";
		else if (i === 15) uuid += 4;
		else if (i === 20) uuid += hexList[(Math.random() * 4) | 8];
		else uuid += hexList[(Math.random() * 16) | 0];
	}
	return uuid.replace(/-/g, "");
};

let unique = 0;
export function buildShortUUID(prefix = ""): string {
	const time = Date.now();
	const random = Math.floor(Math.random() * 1000000000);
	unique++;
	return `${prefix}_${random}${unique}${string(time)}`;
}
//数组解构字段
export const arrDeconstruction = (arr: Array<Record<string, any>>, stringObg: Record<string, string>) => {
	let list: any[] = [];
	for (const key in stringObg) {
		arr.forEach(item => {
			if (key in item) {
				list = [
					...list,
					{
						secdId: "1",
						[key]: item[key]
					}
				];
			} else {
				console.log(`Property "${key}" not found in item.`);
			}
		});
	}
	return list;
};
/**
 * 将日期转换为时间戳
 * @param {string|Date} date - 可以是日期字符串或 Date 对象
 * @param {boolean} isMilliseconds - 是否返回毫秒级时间戳，默认返回秒时间戳
 * @returns {number} - 返回时间戳
 */
export function convertToTimestamp(date: string | number | Date, isMilliseconds = false) {
	// 如果传入的是字符串，先转换为 Date 对象
	const dateObj = new Date(date);
	// 获取时间戳，毫秒级则返回 getTime，否则返回秒级时间戳
	return isMilliseconds ? dateObj.getTime() : Math.floor(dateObj.getTime() / 10000);
}
//过滤
export const filterData = (data: any, filterObject: any) => {
	return data.filter(item => {
		return Object.keys(filterObject).every(key => {
			if (filterObject[key] === undefined) {
				return true;
			}
			return item[key] === filterObject[key];
		});
	});
};
/**
 * 时间戳转换成时间
 * 输出类似 "2025-02-08 17:00:00"
 */
export const formatDate = (date: any) => {
	const y = date.getFullYear();
	const m = ("0" + (date.getMonth() + 1)).slice(-2);
	const d = ("0" + date.getDate()).slice(-2);
	const hh = ("0" + date.getHours()).slice(-2);
	const mm = ("0" + date.getMinutes()).slice(-2);
	const ss = ("0" + date.getSeconds()).slice(-2);
	return y + "-" + m + "-" + d + " " + hh + ":" + mm + ":" + ss;
};
